home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NeXT Education Software Sampler 1992 Fall
/
NeXT Education Software Sampler 1992 Fall.iso
/
Programming
/
Source
/
Weather
/
Weather.app
/
Storm.m
< prev
next >
Wrap
Text File
|
1992-07-29
|
13KB
|
594 lines
/*
* Object to peck on a remote network weather service.
*
* Michael Hawley
* MIT Media Laboratory
* 20 Ames Street
* Cambridge, MA 02139
* mike@media-lab.mit.edu
* Copyright (c) 1991 MIT Media Laboratory
* Burn before reading! This means you!!
*
* Please forward any comments/revisions.
* Keep in mind that this was a one-day knock off;
* much of the complexity is due to the fact that
* we have to parse a telnet conversation that was
* never intended for such.
*/
#import "Storm.h"
#import "Process.h"
#import <appkit/Form.h>
#import <appkit/Font.h>
#import <appkit/Text.h>
#import <appkit/TextField.h>
#import <appkit/Button.h>
#import <appkit/PopUpList.h>
#import <appkit/ScrollView.h>
#import <appkit/Matrix.h>
#import <appkit/NXBrowser.h>
#import <appkit/Speaker.h>
#import <appkit/Listener.h>
#import "MyMenuCell.h"
#import "Defaults.h"
#import "License.h"
@implementation Storm
static int blank(char *s){
while (*s && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')) s++;
return *s? 0 : 1;
}
int StormDebug = 1;
id _status;
extern int Verbose;
char *
path(char *s)
/*
* if 's' is in [NXArgv[0]], return [NXArgv[0]]/s.
* (for looking up internal commands and files in .../Opener.app/...).
*/
{
char t[1024], *q, *r;
static char p[1024];
extern char **NXArgv;
*t = '\0';
sscanf(s,"%s",t);
if (!*t || *t=='(') return s;
r = s + strlen(t);
strcpy(p,*NXArgv);
if (q=rindex(p,'/'))
strcpy(q+1,t);
else
strcpy(p,t);
if (access(p,0)==0){
strcpy(p+strlen(p),r);
return p;
}
return s;
}
static void say(s, a,b,c,d) id s; char *a,*b,*c,*d; {
char p[1024];
sprintf(p,a,b,c,d);
[s setStringValue:p];
[s display];
NXPing();
}
void message(a,b,c,d) char *a,*b,*c,*d; {
char p[1024];
sprintf(p,a,b,c,d);
[_status setStringValue:p];
[_status display];
NXPing();
}
static int eq(char *a, char *b){ return strncmp(a,b,strlen(b))==0; }
static int eqtail(char *s, char *t){ /* true if t appears at end of s */
int tn = strlen(t), sn = strlen(s);
if (tn > sn) return 0;
return strcmp(s+(sn-tn), t)==0;
}
static int streq(char *a, char *b){ return strcmp(a,b)==0; }
static char *strindex(char *s, char *t){
int n = strlen(t);
if (s) while (*s)
if (!strncmp(s, t, n))
return s;
else
s++;
return (char *)0;
}
static int match(char *a, char *b){
return eq(a,b) || strindex(a,b) || strindex(b,a);
}
static char *stripnl(char *s){
char *p;
for (p=s;*p;p++) if (*p == '\n' || *p == '\r') *p = '\0';
return s;
}
id _P;
static void put(P, fmt, a, b, c, d) id P; char *fmt, *a, *b, *c, *d; {
char p[1024];
sprintf(p,fmt,a,b,c,d);
if (Verbose) printf("+ %s\n",p);
[P puts:p];
}
void Put(fmt, a, b, c, d) char *fmt, *a, *b, *c, *d; {
char p[1024];
sprintf(p,fmt,a,b,c,d);
if (Verbose) printf("+ %s\n",p);
if (_P) [_P puts:p];
}
static char *
get(P, s, n) id P; char *s; int n; {
[P gets:s:n];
if (*s && Verbose) printf("> %s",s);
return *s? s : (char *)0;
}
char *
pgets(s,n) char *s; int n; {
[_P gets:s:n];
return *s? s : (char *)0;
}
static char *
flush(P,s) id P; char *s; {
static char t[1024];
while (get(P,t,sizeof t))
if (strindex(t,s)) return t;
sleep(1);
while (get(P,t,sizeof t))
if (strindex(t,s)) return t;
return (char *)0;
}
char *
Flush(s) char *s; {
static char t[1024];
if (_P) return;
while (get(_P,t,sizeof t))
if (strindex(t,s)) return t;
sleep(1);
while (get(_P,t,sizeof t))
if (strindex(t,s)) return t;
return (char *)0;
}
- enable:(BOOL)b {
[attachB setIcon:b? "plug" : "unplug"];
return self;
}
static id _text, _scroll;
- initMatrix {
// from the nib file, we have the help text; keep a pointer to it.
_text = helpText = [scrollView docView];
[_text setDelegate:self];
[_text setMarginLeft:6.0 right:6.0 top:0.0 bottom:0.0];
[_text notifyAncestorWhenFrameChanged:YES];
return self;
}
- setScrollView:anObject {
_scroll = scrollView = anObject;
[self initMatrix];
return self;
}
extern char DefaultFont[];
extern char DefaultFontSize[];
static id fid = (id)0;
static int canconvert = 0;
double atof();
- textWillConvert:textObject fromFont:from toFont:to {
if (canconvert && strcmp(DefaultFont,[from name])==0 &&
atof(DefaultFontSize) == [from pointSize]){
strcpy(DefaultFont,[to name]);
sprintf(DefaultFontSize,"%f",[to pointSize]);
fid = to;
writeDefaults();
}
return to;
}
void
setText(s) char *s; {
static NXPoint origin = {0.0,0.0};
id w = [_scroll window];
if (!fid){
fid = [Font newFont:DefaultFont size:atof(DefaultFontSize)];
}
canconvert=0;
[w disableFlushWindow];
[_text setText:s];
[_text setSel:0:999999];
[_text setSelGray:0.0];
[_text setSelFont:fid];
[_text selectNull];
[_text scrollPoint:&origin];
[_scroll display];
[[w reenableFlushWindow] flushWindow];
NXPing();
canconvert=1;
}
void openFile(char *s){ /* open 's' in workspace */
int ok = 0;
id p = [NXApp appSpeaker];
char t[512];
sprintf(t,"\nThe file\n %s\nwill open in the workspace.",s);
setText(t);
[p setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
[p openFile:s ok:&ok];
if (!ok) sprintf(t,"\nCouldn't open: %s",s), setText(t);
}
isRTF(s) char *s; {
int f = open(s,0);
if (f > 0){
char t[128];
int n = read(f,t,sizeof(t));
close(f);
if (n <= 0) return 0;
return strncmp(t,"{\\rtf",5)==0;
} else
return 0;
}
void
setFile(s) char *s; {
char *p = path(s);
NXStream *f = NXMapFile(p,NX_READONLY);
static NXPoint origin = {0.0,0.0};
id w = [_scroll window];
canconvert=0;
if (!f) return ;
[w disableFlushWindow];
if (isRTF(p)){
[_text setMonoFont:NO];
[_text readRichText:f];
} else {
[_text readText:f];
[_text setSel:0:999999];
[_text setSelGray:0.0];
if (!fid)
fid = [Font newFont:DefaultFont size:atof(DefaultFontSize)];
[_text setSelFont:fid];
[_text selectNull];
canconvert=1;
}
NXCloseMemory(f,NX_FREEBUFFER);
[_text scrollPoint:&origin];
[_scroll display];
[[w reenableFlushWindow] flushWindow];
}
- showHelp:sender {
setFile("info");
return self;
}
#define Case break; case
static char *prompt = "archie>";
squishRtn(char *s){
char *p = s;
while (*p = *s++)
if (*p != '\r') ++p;
}
static char *
getLine(char *s, char *t){ /* read ...\n from s into t; return new s */
char *p = t;
*t = '\0';
squishRtn(s);
while (*s && *s != '\n') *p++ = *s++;
if (*s == '\n') *p++ = *s++;
*p++ = '\0';
if (*t == '\0') return (char *)0;
if (Verbose) printf("- %s",t);
return s;
}
- processOutput:(char *)s {
static char prev[8192]="";
char t[1024], *p=prev;
strcat(prev,s); s = t;
while ((p=getLine(p,s)) &&
(index(s,'\n') || strcmp(s+strlen(s)-2,": ")==0 ||
strcmp(s+strlen(s)-1,":")==0))
execState(0,s);
strcpy(prev,blank(s)?s:"");
return self;
}
static id me;
Command(s) char *s; {
if (!_P) {
substr(s,"$Site",Site);
_P = [Process new:s delegate:me];
}
}
- click:sender {
id c = [[browser matrixInColumn:[browser lastColumn]] selectedCell];
if ([c isLeaf])
[c click:self];
return self;
}
- click2:sender {
return self;
}
ensurelogin(){
[me ensurelogin];
return _P? 1 : 0;
}
- ensurelogin {
//if (!_P) [self login:self];
return self;
}
- login:sender {
if (_P) [_P free]; P = _P = (id)0;
_status = status;
[self setFetch];
ReadState(path("menus"));
[browser setDelegate:self];
[browser setCellPrototype:[[MyMenuCell alloc] init]];
[browser loadColumnZero];
[browser setAction:@selector(click:)];
[browser setDoubleAction:@selector(click2:)];
[browser setTarget:self];
[attachB setIcon:"plug"];
runState("");
return self;
}
void
logout(){
[me logout:me];
}
- logout:sender {
if (P && _P) setState("Detach"), runState("");
if (P) [P terminate:self];
_P = P = (id)0;
[self enable:NO];
[attachB setIcon:"unplug"];
message("not connected.");
return self;
}
extern int sleep();
- attach:sender {
if (eq((char *)[sender icon],"unplug")){
[self login:sender];
} else {
[self logout:sender];
}
return self;
}
/*
* the buttons and commands to run at startup time.
*/
id Fetch[NumFetch];
int FetchSelected = -1;
- setFetch {
int i;
Fetch[0] = fetch1;
Fetch[1] = fetch2;
Fetch[2] = fetch3;
for (i=0;i<NumFetch;i++) [self setFetchText:i:FetchText[i]];
return self;
}
- setFetchText:(int)i:(char *)s {
[Fetch[i] setStringValue:s];
strcpy(FetchText[i],s);
[Fetch[i] display];
return self;
}
- setFetchText:(char *)s {
if (FetchSelected >= 0)
[self setFetchText:FetchSelected:s];
return self;
}
void
setFetchText(s) char *s; {
[me setFetchText:s];
}
- setFetch:(int)i:(int)state {
[Fetch[i] setBackgroundGray:state?1.0:.666];
if (state) [self setFetchText:i:""];
else [Fetch[i] display];
return self;
}
- hitRadio:sender {
int i;
int n = [sender selectedRow], state = [[sender selectedCell] state];
[self setFetch:n:state];
FetchSelected = state? n : -1;
for (i=0; i<NumFetch; i++){
if (i != n || !state){
[[sender cellAt:i:0] setState:0];
[self setFetch:i:0];
}
}
[sender display];
return self;
}
fetchReports() {
int i;
char buf[80000], *p = buf;
while (pgets(buf,1024) && !strindex(buf,curMenuLast())) ;
*buf = '\0';
for (i=0;i<NumFetch;i++){
if (!blank(FetchText[i])){
message("%s. . .",FetchText[i]);
fetchReport(FetchText[i],p);
if (p[0]){
p += strlen(p);
if (i < (NumFetch-1))
strcpy(p,"\n===============================\n");
p += strlen(p);
}
}
}
squishRtn(buf);
squishwhite(buf);
if (*buf) setText(buf);
message("connected!");
}
- setSite:thing {
openDefaults();
site = thing;
[site setTitle:Site];
return self;
}
- hitSite:sender {
char *s = (char *)[[sender selectedCell] title];
strcpy(Site,s);
writeDefaults();
return self;
}
/*
* telnet:
*/
#import <appkit/Pasteboard.h>
#import <appkit/Speaker.h>
#import <appkit/Listener.h>
- copyString:(char *)s {
id p = [Pasteboard new];
[p declareTypes:&NXAsciiPboard num:1 owner:self];
[p writeType:NXAsciiPboard data:s length:strlen(s)];
return self;
}
- launchTerminal:(char *)program {
id p = [NXApp appSpeaker];
port_t t = NXPortFromName("Terminal",NULL);
int ok;
if (t==PORT_NULL) return self;
[p setSendPort:t];
[self copyString:program];
(void)[p msgPaste:&ok];
return self;
}
- telnet:sender {
char p[1024];
sprintf(p,"telnet %s 3000\n",Site);
[self launchTerminal:p];
return self;
}
- sendComments:sender {
return self;
}
#import <appkit/PrintInfo.h>
- print:sender {
static int p = 0;
if (!p){
p++;
[[NXApp printInfo] setScalingFactor:.9];
}
return [_text printPSCode:sender];
}
- pageLayout:sender {
return [NXApp runPageLayout:sender];
}
+ new {
me = self = [[Storm alloc] init];
return self;
}
- free {
[self logout:self];
return [super free];
}
- appDidInit:sender {
openDefaults();
if (FirstUse()) [license show:self];
[attachB performClick:sender];
return self;
}
- appWillTerminate:sender {
[self logout:self];
System("/bin/rm -rf /tmp/W_maps /tmp/W_scratch &");
writeDefaults();
return self;
}
- (int)browser:sender fillMatrix:matrix inColumn:(int)column {
char *s = "Main";
if (column>0){
id c;
c = [[browser matrixInColumn:[browser lastColumn]] selectedCell];
s = [c get];
}
setMenu(s);
return numItem(s);
}
- browser:sender loadCell:c atRow:(int)row inColumn:(int)column {
[c setStringValueNoCopy:curMenuItem(row)];
return self;
}
- browserDidScroll:sender {
static int pc = -1;
int c = [browser firstVisibleColumn];
ensurelogin();
if (pc == c) return self;
pc = c;
if (c == 0) Put("m\n"), Flush("Change scroll"), setMenu("Main");
else
[[[browser matrixInColumn:0] selectedCell] click:self];
return self;
}
@end